package com.qq.websocket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value="/chat/{userid}")
@Component
public class MyWebSocket {

    private static Logger log = LoggerFactory.getLogger(MyWebSocket.class);
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //concurrent包的线程安全HashMap，用来存放每个客户端对应的MyWebSocket对象。
    private static ConcurrentHashMap<String, MyWebSocket> webSocketSetmaps = new ConcurrentHashMap<String,MyWebSocket>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    //用户ID，用于点对点发送消息
    private String userid;

    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session, @PathParam("userid")String  userid) {
        this.session = session;
        this.userid=userid;

        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入！当前在线人数为" + onlineCount);
        //messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
        //把自己的信息加入到map当中去
        webSocketSetmaps.put(userid,this);
        //给自己发一条消息：告诉自己现在都有谁在线
        Map<String,Object> map2 = Maps.newHashMap();
        map2.put("messageType",3);
        //移除掉自己
        Set<String> set = webSocketSetmaps.keySet();
        map2.put("onlineUsers",set);
        sendMessageTo(JSONUtil.toJsonStr(map2),userid);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSetmaps.remove(this.userid);  //从set中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session)
    {
        try {
            log.info("来自客户端消息：" + message+"客户端的id是："+session.getId());
            JSONObject jsonObject = JSONUtil.parseObj(message);
            String textMessage = jsonObject.getStr("message");
            String fromusername = jsonObject.getStr("username");
            String tousername = jsonObject.getStr("to");
            //如果不是发给所有，那么就发给某一个人
            //messageType 1代表上线 2代表下线 3代表在线名单  4代表普通消息
            Map<String,Object> map1 = Maps.newHashMap();
            map1.put("messageType",4);
            map1.put("textMessage",textMessage);
            map1.put("fromusername",fromusername);
            if(tousername.equals("All")){
                map1.put("tousername","所有人");
                sendMessageAll(JSONUtil.toJsonStr(map1),fromusername);
            }else{
                map1.put("tousername",tousername);
                sendMessageTo(JSONUtil.toJsonStr(map1),tousername);
            }
        }
        catch (Exception e){
            log.info("发生了错误了");
        }

    }

    //   点对点发送消息
    public void sendMessageTo(String message, String toUserName) {
        MyWebSocket tar = webSocketSetmaps.get(toUserName);
        if(tar==null){
            //TODO  发送对象不在线的消息放入消息缓存
        }else{
            tar.session.getAsyncRemote().sendText(message);
        }
    }

    public static void SendMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText(String.format("%s (From Server，Session ID=%s)",message,session.getId()));
        } catch (IOException e) {
            log.error("发送消息出错：{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 群发消息
     * @param message
     * @param FromUserName
     * @throws IOException
     */
    public void sendMessageAll(String message,String FromUserName) throws IOException {
        for (MyWebSocket item : webSocketSetmaps.values()) {
            item.session.getAsyncRemote().sendText(message);
        }
    }

    /**
      * 发生错误时调用
     * */
     @OnError
     public void onError(Session session, Throwable error) {
     System.out.println("发生错误");
     error.printStackTrace();
     }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        MyWebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        MyWebSocket.onlineCount--;
    }


}
